﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;

namespace Bubblez
{
    public partial class frmmain : Form
    {
        // Path Variables
        public string WoW_Path = "C:\\Program Files\\World of Warcraft";
        public string WTF_Path = "\\WTF";
        public string UI_Path = "\\Interface\\Addons";
        public string Filter_Path = Application.StartupPath + "\\Filters";
        public string Back_Path = Application.StartupPath + "\\Data\\Backup";
        public string Data_Path = Application.StartupPath + "\\Data";
        public string Log_Path = Application.StartupPath + "\\Log";

        // Search Engine
        public bool firstSearch = true;
        public bool Search_Title = true;
        public bool Search_Author = true;
        public bool Search_Notes = true;
        public bool Search_Dependencies = true;
        public int Search_Mode = 3;
        public int[] Results;
        public int[] Search_Title_Result = new int[0];
        public int[] Search_Author_Result = new int[0];
        public int[] Search_Notes_Result = new int[0];
        public int[] Search_hasDep_Result = new int[0];

        // Filter Options
        public string WildCard = "*";
        public bool EnableExternalFilters = true;
        public bool EnableFiltersDuringSearch = true;
        public bool EnableDefaultFilters = true;

        // Filter Engine
        public int[] ExcludeList = new int[0];
        public int[] Filter_Title_Result = new int[0];
        public int[] Filter_Author_Result = new int[0];
        public int[] Filter_Notes_Result = new int[0];
        public int[] Filter_hasDep_Result = new int[0];

        // Default Filters
        public string[] Filter_Default = new string[] { "DEFAULT_Blizzard" };
        public string[] Filter_Default_Name = new string[] { "Blizzard Addons" };
        public string[] Filter_Default_String = new string[] { "Blizzard" };
        public bool[] Filter_Default_Title = new bool[] { false };
        public bool[] Filter_Default_Author = new bool[] { true };
        public bool[] Filter_Default_Notes = new bool[] { false };
        public bool[] Filter_Default_HasDep = new bool[] { false };
        public int[] Filter_Default_Mode = new int[] { 1 };
        public bool[] Filter_Default_Enabled = new bool[] { true };

        // External Filters
        public string[] Filter;
        public string[] Filter_Name;
        public string[] Filter_String;
        public bool[] Filter_Title;
        public bool[] Filter_Author;
        public bool[] Filter_Notes;
        public bool[] Filter_HasDep;
        public int[] Filter_Mode;
        public bool[] Filter_Enabled;

        // Addon 'Database' Variables
        public string[] Addon;
        public string[] Addon_Name;
        public bool[] Addon_Enabled;
        public string[] Addon_Title;
        public string[] Addon_Author;
        public string[] Addon_Version;
        public string[] Addon_Dependencies;
        public string[] Addon_Notes;
        public string[] Addon_BackedUp;
        public string[] AddonsFile;

        // File Variables
        public string Tree_TarDir;
        public string Tree_Root;
        public string[] Tree_Directories;
        public string[] Tree_Files;

        // Form Events
        public frmmain()
        {
            InitializeComponent();
        }
        private void frmmain_Load(object sender, EventArgs e)
        {
            sbStatus.Text = "Loading Bubblez...";
            this.Update();
            if (File.Exists(Data_Path + "\\Settings.ini"))
                Load_Settings();
            else
                Settup_Files();
            sbStatus.Text = "Loading Addons";
            this.Update();
            Addons_Load();
            sbStatus.Text = "Loading Filters";
            this.Update();
            Filter_Load();
            Search_Engine(WildCard, Search_Notes, Search_Author, Search_Notes, Search_Dependencies, Search_Mode);
            sbStatus.Text = "Populating Lists";
            this.Update();
            Populate_List();
            sbStatus.Text = "Ready";
            this.Update();

            double spacing = grpAction.Width / 4.6;
            int margin = 10;

            cmdEnable.Left = margin;
            cmdDisable.Left = (Convert.ToInt16(spacing) * 1 + margin);
            cmdRestore.Left = (Convert.ToInt16(spacing) * 2 + margin);
            cmdBackup.Left = (Convert.ToInt16(spacing) * 3 + margin);
            cmdDelete.Left = (Convert.ToInt16(spacing) * 4 + margin);
        }
        private void frmmain_Resize(object sender, EventArgs e)
        {
            lstbox.Width = this.Width - 30;
            grpAction.Width = this.Width - 30;
            grpinfo.Width = this.Width - 30;
            txtSearch.Width = this.Width - 30;

            grpinfo.Top = this.Height - (grpinfo.Height + strip.Height + 42);
            grpAction.Top = grpinfo.Top - grpAction.Height - 6;
            txtSearch.Top = grpAction.Top - txtSearch.Height - 6;
            lstbox.Height = txtSearch.Top - lstbox.Top - 4;

            double spacing = grpAction.Width / 4.6;
            int margin = 10;

            cmdEnable.Left = margin;
            cmdDisable.Left = (Convert.ToInt16(spacing) * 1 + margin);
            cmdRestore.Left = (Convert.ToInt16(spacing) * 2 + margin);
            cmdBackup.Left = (Convert.ToInt16(spacing) * 3 + margin);
            cmdDelete.Left = (Convert.ToInt16(spacing) * 4 + margin);
        }
        private void frmmain_Enter(object sender, EventArgs e)
        {
            Load_Settings();
        }
        private void lstbox_Enter(object sender, EventArgs e)
        {
            Load_Settings();
        }
        private void menuStrip_Enter(object sender, EventArgs e)
        {
            Load_Settings();
        }
        private void Settup_Files()
        {
            string[] contents = new string[16];

            WoW_Path = "C:\\Program Files\\World of Warcraft";
            WTF_Path = "\\WTF";
            UI_Path = "\\Interface\\Addons";
            Filter_Path = Application.StartupPath + "\\Filters";
            Back_Path = Application.StartupPath + "\\Data\\Backup";
            Data_Path = Application.StartupPath + "\\Data";
            Log_Path = Application.StartupPath + "\\Log";

            Search_Title = true;
            Search_Author = true;
            Search_Notes = true;
            Search_Dependencies = true;

            WildCard = "*";
            EnableExternalFilters = true;
            EnableFiltersDuringSearch = true;
            EnableDefaultFilters = true;

            if (Directory.Exists(Data_Path) == false)
                Directory.CreateDirectory(Data_Path);
            if (Directory.Exists(Back_Path) == false)
                Directory.CreateDirectory(Back_Path);
            if (Directory.Exists(Back_Path + "\\_Archives") == false)
                Directory.CreateDirectory(Back_Path + "\\_Archives");
            if (Directory.Exists(Filter_Path) == false)
                Directory.CreateDirectory(Filter_Path);


            contents[0] = "WoW_Path=" + WoW_Path;
            contents[1] = "WTF_Path=" + WTF_Path;
            contents[2] = "UI_Path=" + UI_Path;
            contents[3] = "Filter_Path=" + Filter_Path;
            contents[4] = "Back_Path=" + Back_Path;
            contents[5] = "Data_Path=" + Data_Path;
            contents[6] = "Log_Path=" + Log_Path;

            contents[7] = "WildCard=" + WildCard;
            contents[8] = "EnableExternalFilters=" + Convert.ToString(EnableExternalFilters);
            contents[9] = "EnableFiltersDuringSearch=" + Convert.ToString(EnableFiltersDuringSearch);
            contents[10] = "EnableDefaultFilters=" + Convert.ToString(EnableDefaultFilters);

            contents[11] = "Search_Title=" + Convert.ToString(Search_Title);
            contents[12] = "Search_Author=" + Convert.ToString(Search_Author);
            contents[13] = "Search_Notes=" + Convert.ToString(Search_Notes);
            contents[14] = "Search_Dependencies=" + Convert.ToString(Search_Dependencies);
            contents[15] = "Search_Mode=" + Convert.ToString(Search_Mode);

            File.WriteAllLines(Data_Path + "\\Settings.ini", contents);

        }
        private void Load_Settings()
        {
            string[] contents = File.ReadAllLines(Data_Path + "\\Settings.ini");
            string[] data;

            data = contents[0].Split('=');
            WoW_Path = data[1];
            data = contents[1].Split('=');
            WTF_Path = data[1];
            data = contents[2].Split('=');
            UI_Path = data[1];
            data = contents[3].Split('=');
            Filter_Path = data[1];
            data = contents[4].Split('=');
            Back_Path = data[1];
            data = contents[5].Split('=');
            Data_Path = data[1];
            data = contents[6].Split('=');
            Log_Path = data[1];
            data = contents[7].Split('=');
            WildCard = data[1];
            data = contents[8].Split('=');
            EnableExternalFilters = Convert.ToBoolean(data[1]);
            data = contents[9].Split('=');
            EnableFiltersDuringSearch = Convert.ToBoolean(data[1]);
            data = contents[10].Split('=');
            EnableDefaultFilters = Convert.ToBoolean(data[1]);
            data = contents[11].Split('=');
            Search_Title = Convert.ToBoolean(data[1]);
            data = contents[12].Split('=');
            Search_Author = Convert.ToBoolean(data[1]);
            data = contents[13].Split('=');
            Search_Notes = Convert.ToBoolean(data[1]);
            data = contents[14].Split('=');
            Search_Dependencies = Convert.ToBoolean(data[1]);
            data = contents[15].Split('=');
            Search_Mode = Convert.ToInt16(data[1]);
        }

        // Addon Management
        private void Addons_Load()
        {
            string[] a = Directory.GetDirectories(WoW_Path + UI_Path);
            Addon = new string[a.Length];
            Addon_Name = new string[a.Length];
            Addon_Title = new string[a.Length];
            Addon_Author = new string[a.Length];
            Addon_Version = new string[a.Length];
            Addon_Dependencies = new string[a.Length];
            Addon_Notes = new string[a.Length];
            Addon_BackedUp = new string[a.Length];

            Addon = Directory.GetDirectories(WoW_Path + UI_Path);

            for (int i = 0; i <= Addon.Length - 1; i++)
                Addon_Name[i] = Addon[i].Substring(WoW_Path.Length + UI_Path.Length, Addon[i].Length - WoW_Path.Length - UI_Path.Length);

            for (int i = 0; i <= Addon.Length - 1; i++)
                TOC_Load(Addon[i] + Addon_Name[i] + ".toc", i);
        }
        private void Populate_List()
        {
                for (int i = 0; i < Results.Length; i++)
                {
                    Addon_Name[Results[i]] = Addon[Results[i]].Substring((WoW_Path.Length + UI_Path.Length), Addon[Results[i]].Length - WoW_Path.Length - UI_Path.Length);
                    TOC_Load(Addon[Results[i]] + "\\" + Addon_Name[Results[i]] + ".toc", Results[i]);
                    if (Addon_Name[Results[i]] == "")
                        lstbox.Items.Add(Addon_Title[Results[i]].Substring(1, Addon_Name[Results[i]].Length - 1));
                    else
                    {
                        lstbox.Items.Add(Addon_Title[Results[i]]);
                    }
                }
        }
        private void Reload_Addons()
        {
            int Last_Index = lstbox.SelectedIndex;
            lstbox.Items.Clear();
            Addons_Load();
            Populate_List();
            if (Last_Index >= lstbox.Items.Count)
                lstbox.SelectedIndex = Last_Index - 1;
            else
                lstbox.SelectedIndex = Last_Index;
        }

        // Enable / Disables Addon
        private void Change_Load_State(string addon, string state)
        {
            Load_Tree(WoW_Path + WTF_Path);
            bool found = false;
            string newLine;
            string[] tmp;

            for (int i = 0; i < Tree_Files.Length; i++)
            {
                string[] fileName = Tree_Files[i].Split('\\');
                if (fileName[fileName.Length - 1] == "AddOns.txt")
                {
                    AddonsFile = File.ReadAllLines(WoW_Path + Tree_Files[i]);
                    for (int c = 0; c < AddonsFile.Length; c++)
                    {
                        string[] part = AddonsFile[c].Split(':');
                        if (part[0] == addon)
                        {
                            AddonsFile[c] = addon + ": " + state;
                            found = true;
                        }
                    }
                    if (found == true)
                        File.WriteAllLines(WoW_Path + Tree_Files[i], AddonsFile);
                    else
                    {
                        newLine = addon + ": " + state;
                        tmp = new string[AddonsFile.Length];
                        for (int c = 0; c < AddonsFile.Length; c++)
                            tmp[c] = AddonsFile[c];

                        AddonsFile = new string[tmp.Length + 1];

                        for (int c = 0; c < tmp.Length; c++)
                            AddonsFile[c] = tmp[c];

                        AddonsFile[AddonsFile.Length - 1] = newLine;

                        File.WriteAllLines(WoW_Path + Tree_Files[i], AddonsFile);
                    }
                    found = false;
                }
            }
        }

        //Filter stuff
        private void Filter_Load()
        {
            string[] f = Directory.GetFiles(Application.StartupPath + "\\Filters");
            if (f.Length > 0)
            {
                Filter = new string[f.Length];
                Filter_Name = new string[f.Length];
                Filter_String = new string[f.Length];
                Filter_Title = new bool[f.Length];
                Filter_Author = new bool[f.Length];
                Filter_Notes = new bool[f.Length];
                Filter_HasDep = new bool[f.Length];
                Filter_Mode = new int[f.Length];
                Filter_Enabled = new bool[f.Length];

                Filter = Directory.GetFiles(Application.StartupPath + "\\Filters");
                for (int i = 0; i <= f.Length - 1; i++)
                    Filter_LoadFile(Filter[i], i);
            }

        }
        private void Filter_LoadFile(string path, int index)
        {
            if (File.Exists(path) == false)
            {
                Filter_String[index] = "Error: File Not Found (" + path + ")";
                Filter_Name[index] = "Error: File Not Found (" + path + ")";
                Filter_Title[index] = false;
                Filter_Author[index] = false;
                Filter_Notes[index] = false;
                Filter_HasDep[index] = false;
                Filter_Enabled[index] = false;
            }
            string[] line = File.ReadAllLines(path);
            for (int i = 0; i <= line.Length - 1; i++)
            {
                if ((line[i].Substring(0, 2)).ToLower() == "na")
                    Filter_Name[index] = line[i].Substring(5, line[i].Length - 5);
                else if ((line[i].Substring(0, 2)).ToLower() == "st")
                    Filter_String[index] = line[i].Substring(7, line[i].Length - 7);
                else if ((line[i].Substring(0, 2)).ToLower() == "ti")
                    Filter_Title[index] = Convert.ToBoolean(line[i].Substring(6, line[i].Length - 6));
                else if ((line[i].Substring(0, 2)).ToLower() == "au")
                    Filter_Author[index] = Convert.ToBoolean(line[i].Substring(7, line[i].Length - 7));
                else if ((line[i].Substring(0, 2)).ToLower() == "no")
                    Filter_Notes[index] = Convert.ToBoolean(line[i].Substring(6, line[i].Length - 6));
                else if ((line[i].Substring(0, 2)).ToLower() == "ha")
                    Filter_HasDep[index] = Convert.ToBoolean(line[i].Substring(7, line[i].Length - 7));
                else if ((line[i].Substring(0, 2)).ToLower() == "mo")
                    Filter_Mode[index] = Convert.ToInt16(line[i].Substring(5, line[i].Length - 5));
                else if ((line[i].Substring(0, 2)).ToLower() == "en")
                    Filter_Enabled[index] = Convert.ToBoolean(line[i].Substring(8, line[i].Length - 8));

            }
        }
        private void TOC_Load(string path, int index)
        {
            if (File.Exists(path) == false)
            {
                Addon_Title[index] = Addon_Name[index].Substring(1, Addon_Name[index].Length - 1);
                Addon_Author[index] = "None Present";
                Addon_Notes[index] = "None Present";
                Addon_Version[index] = "None Present";
                Addon_Dependencies[index] = "None Present";

                if ((Addon_Name[index].Length >= 9) && ((Addon_Name[index].ToLower()).Substring(1, 8) == "blizzard"))
                    Addon_Author[index] = "Blizzard";
                return;
            }
            string[] line = File.ReadAllLines(path);
            for (int i = 0; i <= line.Length - 1; i++)
            {
                if ((line[i] != "") || (line[i].Length > 2))
                {
                    if (line[i].Substring(0, 2) == "##")
                    {
                        if (line[i].Substring(3, 1) == "I")
                            Addon_Version[index] = line[i].Substring(14, line[i].Length - 14);
                        else if (line[i].Substring(3, 1) == "T")
                            Addon_Title[index] = TOC_getTitle(line[i].Substring(3, line[i].Length - 3), index);
                        else if (line[i].Substring(3, 6) == "Notes:")
                            Addon_Notes[index] = (line[i].Substring(10, line[i].Length - 10));
                        else if (line[i].Substring(3, 2) == "Re")
                            Addon_Dependencies[index] = line[i].Substring(17, line[i].Length - 17);
                        else if (line[i].Substring(3, 3) == "Dep")
                            Addon_Dependencies[index] = line[i].Substring(17, line[i].Length - 17);
                        else if (line[i].Substring(3, 1) == "A")
                            Addon_Author[index] = line[i].Substring(11, line[i].Length - 11);
                    }
                }
            }
            for (int i = 0; i < Addon_Title.Length; i++)
            {

                if (Addon_Title[i] == null)
                    Addon_Title[i] = Addon_Name[index].Substring(1, Addon_Name[index].Length - 1);
                if (Addon_Author[i] == null)
                    Addon_Author[i] = "None";
                if (Addon_Notes[i] == null)
                    Addon_Notes[i] = "None";
                if (Addon_Version[i] == null)
                    Addon_Version[i] = "None";
                if (Addon_Dependencies[i] == null)
                    Addon_Dependencies[i] = "None";
            }
        }
        private string TOC_getTitle(string n, int index)
        {
            int l = n.Length;
            if (l >= 5)
            {
                if (n.Substring(5, 1) == ":")
                    if (n.Substring(6, 1) == " ")
                        return TOC_Filter(n.Substring(7, n.Length - 7));
                    else
                        return TOC_Filter(n.Substring(6, n.Length - 6));
                else
                    return TOC_Filter(Addon_Title[index]);
            }
            else
                return TOC_Filter(Addon_Title[index]);
        }
        private string TOC_Filter(string s)
        {
            bool filter = false;
            string result = "";
            for (int i = 0; i <= s.Length - 2; i++)
            {
                if (s.Substring(i, 2) == "|r")
                    filter = true;
            }
            if (filter == false)
                return s;

            string[] c = s.Split('|');
            for (int i = 0; i <= c.Length - 1; i++)
            {
                if (c[i].Length >= 1)
                {
                    if ((c[i].Substring(0, 1) == "r") && (i == 1))
                    {
                        if (s.Substring(0, 1) != "|")
                            result += c[i - 1];
                        else
                        {
                            if (c[i - 1].Length > 9)
                                result += c[i - 1].Substring(9, c[i - 1].Length - 9);
                        }
                    }
                    if ((c[i].Substring(0, 1) == "r") && (i != 0) && (c[i - 1].Length > 9))
                    {
                        result += (c[i - 1].Substring(9, c[i - 1].Length - 9));
                        if (c[i].Length > 1)
                            result += c[i].Substring(1, c[i].Length - 1);
                    }
                    else if ((c[i].Substring(0, 1) == "r") && (c[i].Length > 1))
                        result += c[i].Substring(1, c[i].Length - 1);
                    else if ((c[i].Substring(0, 1) != "r") && (i == 1))
                        result += c[i - 1];
                }
            }
            return result;
        }

        private void lstbox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstbox.SelectedIndex != -1)
            {
                int index = lstbox.SelectedIndex;
                lblname.Text = "Name: " + Addon_Title[Results[index]];
                lblauthor.Text = "Author: " + Addon_Author[Results[index]];
                lblnotes.Text = "Notes: " + Addon_Notes[Results[index]];
                lblversion.Text = "Version: " + Addon_Version[Results[index]];
                lbldep.Text = "Dependencies: " + Addon_Dependencies[Results[index]];

                if (Addon_Title[Results[index]].Length >= 9)
                {
                    if (Addon_Title[Results[index]].Substring(0, 9) == "Blizzard_")
                    {
                        cmdEnable.Enabled = false;
                        cmdDisable.Enabled = false;
                    }
                    else
                    {
                        cmdEnable.Enabled = true;
                        cmdDisable.Enabled = true;
                    }
                }
            }
        }

        // Menu Items
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        private void configureFiltersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmfilters frm = new frmfilters();
            frm.Show();
        }
        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmoptions frm = new frmoptions();
            frm.Show();
        }
        private void backUpAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool found = false;
            for (int c = 0; c < lstbox.Items.Count; c++)
            {
                sbStatus.Text = "Backing Up: " + Addon_Title[c] + " (" + c + "/" + lstbox.Items.Count + ")";
                this.Update();
                string[] Directories = Directory.GetDirectories(Back_Path);
                for (int i = 0; i < Directories.Length; i++)
                {
                    string[] aName = Directories[i].Split('\\');
                    if (aName[aName.Length - 1] == Addon_Name[c].Substring(1, Addon_Name[c].Length - 1))
                    {
                        Load_Tree(Directories[i]);
                        Copy_Tree(Back_Path + "\\_Archives" + Addon_Name[c], true, true);
                        Rename_Directory(Back_Path + "\\_Archives" + Addon_Name[c] + Addon_Name[c], Backup_Name(Addon_Name[c].Substring(1, Addon_Name[c].Length - 1)));
                        Directory.Delete(Back_Path + Addon_Name[c], true);
                        Load_Tree(Addon[c]);
                        Copy_Tree(Back_Path, true, true);
                        found = true;
                    }
                }
                if (found == false)
                {
                    Load_Tree(Addon[c]);
                    Copy_Tree(Back_Path, true, true);
                }
                found = false;
            }
            sbStatus.Text = "Ready";
        }
        private void dumpBackupDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            sbStatus.Text = "Deleting Contents of Back Up directory...";
            this.Update();
            try
            {
                Directory.Delete(Back_Path, true);
            }
            catch
            {
            }
            sbStatus.Text = "Ready";
        }
        private void enableAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < Addon.Length; i++)
            {
                sbStatus.Text = "Enabling: " + Addon_Title[i];
                this.Update();
                if (Addon_Title[i].Length >= 9)
                {
                    if ((Addon_Title[i].Substring(0, 9)) != "Blizzard_")
                        Change_Load_State(Addon_Name[i].Substring(1, Addon_Name[i].Length - 1), "enabled");
                }
            }
            sbStatus.Text = "Ready";
            this.Update();
        }
        private void disableAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < Addon.Length; i++)
            {
                sbStatus.Text = "Disabling: " + Addon_Title[i];
                this.Update();
                if (Addon_Title[i].Length >= 9)
                {
                    if (Addon_Title[i].Substring(0, 9) != "Blizzard_")
                        Change_Load_State(Addon_Name[i].Substring(1, Addon_Name[i].Length - 1), "disabled");
                }
            }
            sbStatus.Text = "Ready";
            this.Update();
        }

        // Buttons
        private void cmdEnable_Click(object sender, EventArgs e)
        {
            Change_Load_State(Addon_Name[lstbox.SelectedIndex].Substring(1, Addon_Name[lstbox.SelectedIndex].Length - 1), "enabled");
        }
        private void cmdDisable_Click(object sender, EventArgs e)
        {
            Change_Load_State(Addon_Name[lstbox.SelectedIndex].Substring(1, Addon_Name[lstbox.SelectedIndex].Length - 1), "disabled");
        }
        private void cmdRestore_Click(object sender, EventArgs e)
        {
            string restore;

            if (Directory.Exists(Back_Path + Addon_Name[lstbox.SelectedIndex]) == true)
            {
                restore = Convert.ToString(MessageBox.Show("Would you like to restore " + Addon_Title[lstbox.SelectedIndex] + " to an earlier installation? (" + Directory.GetCreationTime(Back_Path + Addon_Name[lstbox.SelectedIndex]) + ")", "Restore", MessageBoxButtons.YesNo));
                if (restore == "Yes")
                {
                    cmdBackup_Click(null, null);
                    sbStatus.Text = "Restoring: " + Addon_Title[lstbox.SelectedIndex];
                    this.Update();
                    Load_Tree(Back_Path + Addon_Name[lstbox.SelectedIndex]);
                    Copy_Tree(Addon[lstbox.SelectedIndex], true, true);
                    sbStatus.Text = "Ready";
                    this.Update();
                }

            }
            else
            {
                restore = Convert.ToString(MessageBox.Show("There is no active restore file for " + Addon_Title[lstbox.SelectedIndex] + ". Would you like to create one?", "No Registered Backup", MessageBoxButtons.YesNo, MessageBoxIcon.Question));
                if (restore == "Yes")
                    cmdBackup_Click(null, null);

            }
        }
        private void cmdBackup_Click(object sender, EventArgs e)
        {
            bool found = false;
            string[] Directories = Directory.GetDirectories(Back_Path);
            if (lstbox.SelectedIndex == -1)
                MessageBox.Show("No Addon Selected.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
            {
                sbStatus.Text = "Backing Up: " + Addon_Title[lstbox.SelectedIndex];
                this.Update();
                for (int i = 0; i < Directories.Length; i++)
                {
                    string[] aName = Directories[i].Split('\\');
                    if (aName[aName.Length - 1] == Addon_Name[lstbox.SelectedIndex].Substring(1, Addon_Name[lstbox.SelectedIndex].Length - 1))
                    {
                        Load_Tree(Directories[i]);
                        Copy_Tree(Back_Path + "\\_Archives" + Addon_Name[lstbox.SelectedIndex], true, true);
                        Rename_Directory(Back_Path + "\\_Archives" + Addon_Name[lstbox.SelectedIndex] + Addon_Name[lstbox.SelectedIndex], Backup_Name(Addon_Name[lstbox.SelectedIndex].Substring(1, Addon_Name[lstbox.SelectedIndex].Length - 1)));
                        Directory.Delete(Back_Path + Addon_Name[lstbox.SelectedIndex], true);
                        Load_Tree(Addon[lstbox.SelectedIndex]);
                        Copy_Tree(Back_Path, true, true);
                        found = true;
                    }
                }
                if (found == false)
                {
                    Load_Tree(Addon[lstbox.SelectedIndex]);
                    Copy_Tree(Back_Path, true, true);
                }
                sbStatus.Text = "Ready";
                this.Update();
            }
        }
        private void cmdDelete_Click(object sender, EventArgs e)
        {
            string delete = Convert.ToString(MessageBox.Show("Are you sure you want to delete " + Addon_Title[lstbox.SelectedIndex] + " and all of it's contents?", "Confrim Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation));
            if (delete == "Yes")
            {
                Directory.Delete(Addon[lstbox.SelectedIndex], true);
                Reload_Addons();
            }
        }

        // Search GUI
        private void txtSearch_Enter(object sender, EventArgs e)
        {
            Load_Settings();
            if (firstSearch == true)
            {
                txtSearch.Text = "";
                txtSearch.ForeColor = System.Drawing.Color.Black;
                firstSearch = false;
            }
        }
        private void txtSearch_Leave(object sender, EventArgs e)
        {
            if (txtSearch.Text == "")
            {
                txtSearch.Text = "Search";
                txtSearch.ForeColor = System.Drawing.Color.Gray;
                lstbox.Items.Clear();
                Search_Engine(WildCard, Search_Title, Search_Author, Search_Notes, Search_Dependencies, Search_Mode);
                Populate_List();
                firstSearch = true;
            }
        }
        private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            if (firstSearch == false)
            {
                lstbox.Items.Clear();
                if (txtSearch.Text == "")
                {
                    Search_Engine(WildCard, Search_Title, Search_Author, Search_Notes, Search_Dependencies, Search_Mode);
                    Reconstruct_Search_Results();
                }
                else if (txtSearch.Text == WildCard)
                {
                    Search_Engine(WildCard, Search_Title, Search_Author, Search_Notes, Search_Dependencies, Search_Mode);
                    Reconstruct_Search_Results();
                }
                else
                {
                    Search_Engine(txtSearch.Text, Search_Title, Search_Author, Search_Notes, Search_Dependencies, Search_Mode);
                    Reconstruct_Search_Results();
                }

                for (int i = 0; i < Results.Length; i++)
                    lstbox.Items.Add(Addon_Title[Results[i]]);
            }
        }

        private string Backup_Name(string name)
        {
            string newName;

            newName = name + "_" + Convert.ToString(DateTime.Now.DayOfYear) + Convert.ToString(DateTime.Now.Minute) + Convert.ToString(DateTime.Now.Second) + Convert.ToString(DateTime.Now.Millisecond);
            return newName;
        }

        // File Actions
        private void Load_Tree(string folder)
        {
            string[] fdr = folder.Split('\\');
            Tree_TarDir = fdr[fdr.Length - 1];
            Tree_Root = Convert.ToString(Directory.GetParent(folder));
            string[] OI;
            string[] NI;

            Tree_Directories = Directory.GetDirectories(folder);
            Tree_Files = Directory.GetFiles(folder);

            for (int i = 0; i < Tree_Directories.Length; i++)
            {
                OI = new string[Tree_Directories.Length];
                NI = new string[Directory.GetDirectories(Tree_Directories[i]).Length];
                NI = Directory.GetDirectories(Tree_Directories[i]);

                for (int c = 0; c < Tree_Directories.Length; c++)
                    OI[c] = Tree_Directories[c];

                Tree_Directories = new string[Tree_Directories.Length + NI.Length];

                for (int c = 0; c < OI.Length; c++)
                    Tree_Directories[c] = OI[c];

                for (int c = OI.Length; c < NI.Length + OI.Length; c++)
                    Tree_Directories[c] = NI[c - OI.Length];
            }

            for (int i = 0; i < Tree_Directories.Length; i++)
            {
                OI = new string[Tree_Files.Length];
                NI = new string[Directory.GetFiles(Tree_Directories[i]).Length];
                NI = Directory.GetFiles(Tree_Directories[i]);

                for (int c = 0; c < Tree_Files.Length; c++)
                    OI[c] = Tree_Files[c];

                Tree_Files = new string[Tree_Files.Length + NI.Length];

                for (int c = 0; c < OI.Length; c++)
                    Tree_Files[c] = OI[c];

                for (int c = OI.Length; c < NI.Length + OI.Length; c++)
                    Tree_Files[c] = NI[c - OI.Length];
            }

            for (int i = 0; i < Tree_Directories.Length; i++)
                Tree_Directories[i] = Tree_Directories[i].Substring(Tree_Root.Length, Tree_Directories[i].Length - Tree_Root.Length);
            for (int i = 0; i < Tree_Files.Length; i++)
                Tree_Files[i] = Tree_Files[i].Substring(Tree_Root.Length, Tree_Files[i].Length - Tree_Root.Length);


        }
        private void Copy_Tree(string destination, bool includeFileStructure, bool overwrite)
        {
            if (includeFileStructure == true)
            {
                if (Tree_Directories.Length == 0)
                    Directory.CreateDirectory(destination + "\\" + Tree_TarDir);

                for (int i = 0; i < Tree_Directories.Length; i++)
                    Directory.CreateDirectory(destination + Tree_Directories[i]);
                for (int i = 0; i < Tree_Files.Length; i++)
                    File.Copy(Tree_Root + Tree_Files[i], destination + Tree_Files[i], true);
            }
            else
            {
                if (Tree_Directories.Length == 0)
                    Directory.CreateDirectory(destination + "\\" + Tree_TarDir);

                for (int i = 0; i < Tree_Directories.Length; i++)
                    Directory.CreateDirectory(destination + Tree_Directories[i]);
            }
        }
        private void Move_Tree(string destination, bool includeFileStructure, bool overwrite)
        {
            Copy_Tree(destination, includeFileStructure, overwrite);
            Directory.Delete(Tree_Root + "\\" + Tree_TarDir, true);
        }
        private void Rename_Directory(string folder, string newName)
        {
            Load_Tree(folder);

            string[] path;
            string newPath = "";
            string EF;
            string[] NP = new string[Tree_Directories.Length];
            string[] NF = new string[Tree_Files.Length];
            path = folder.Split('\\');
            path[path.Length - 1] = newName;

            for (int i = 0; i < path.Length; i++)
                newPath += path[i] + "\\";

            for (int i = 0; i < Tree_Directories.Length; i++)
            {
                EF = Tree_Directories[i].Substring(Tree_TarDir.Length + 2, Tree_Directories[i].Length - Tree_TarDir.Length - 2);
                NP[i] = newPath + EF;
            }

            for (int i = 0; i < Tree_Files.Length; i++)
            {
                EF = Tree_Files[i].Substring(Tree_TarDir.Length + 2, Tree_Files[i].Length - Tree_TarDir.Length - 2);
                NF[i] = newPath + EF;
            }

            if (NP.Length == 0)
                Directory.CreateDirectory(newPath);
            for (int i = 0; i < NP.Length; i++)
                Directory.CreateDirectory(NP[i]);
            for (int i = 0; i < NF.Length; i++)
                File.Copy(Tree_Root + Tree_Files[i], NF[i], true);

            Directory.Delete(Tree_Root + "\\" + Tree_TarDir, true);

        }
        private bool Engine_Contains(string parameter, string text)
        {
            for (int i = 0; i <= text.Length - parameter.Length; i++)
            {
                if (text.Substring(i, parameter.Length).ToLower() == parameter.ToLower())
                    return true;
            }
            return false;
        }
        private void Search_Engine(string parameter, bool title, bool author, bool notes, bool hasDep, int mode)
        {
            Search_Title_Result = new int[0];
            Search_Author_Result = new int[0];
            Search_Notes_Result = new int[0];
            Search_hasDep_Result = new int[0];

            int[] tmp;
            if (parameter == WildCard)
            {
                if (title == true)
                {
                    Search_Title_Result = new int[Addon_Title.Length];
                    for (int i = 0; i < Addon_Title.Length; i++)
                        Search_Title_Result[i] = i;
                }
                if (author == true)
                {
                    Search_Author_Result = new int[Addon_Author.Length];
                    for (int i = 0; i < Addon_Author.Length; i++)
                        Search_Author_Result[i] = i;
                }
                if (notes == true)
                {
                    Search_Notes_Result = new int[Addon_Notes.Length];
                    for (int i = 0; i < Addon_Notes.Length; i++)
                        Search_Notes_Result[i] = i;
                }
                if (hasDep == true)
                {
                    Search_hasDep_Result = new int[Addon_Dependencies.Length];
                    for (int i = 0; i < Addon_Dependencies.Length; i++)
                        Search_hasDep_Result[i] = i;
                }

            }
            else
            {
                if (mode == 1)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (parameter == Addon_Title[i])
                            {
                                if (Search_Title_Result.Length > 0)
                                {
                                    tmp = new int[Search_Title_Result.Length];
                                    for (int c = 0; c < Search_Title_Result.Length; c++)
                                        tmp[c] = Search_Title_Result[c];

                                    Search_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Title_Result[c] = tmp[c];

                                    Search_Title_Result[Search_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Title_Result = new int[1];
                                    Search_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (parameter == Addon_Author[i])
                            {
                                if (Search_Author_Result.Length > 0)
                                {
                                    tmp = new int[Search_Author_Result.Length];
                                    for (int c = 0; c < Search_Author_Result.Length; c++)
                                        tmp[c] = Search_Author_Result[c];

                                    Search_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Author_Result[c] = tmp[c];

                                    Search_Author_Result[Search_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Author_Result = new int[1];
                                    Search_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (parameter == Addon_Notes[i])
                            {
                                if (Search_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Search_Notes_Result.Length];
                                    for (int c = 0; c < Search_Notes_Result.Length; c++)
                                        tmp[c] = Search_Notes_Result[c];

                                    Search_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Search_Notes_Result.Length; c++)
                                        Search_Notes_Result[c] = tmp[c];

                                    Search_Notes_Result[Search_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Notes_Result = new int[1];
                                    Search_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Search_hasDep_Result.Length; i++)
                        {
                            if (parameter == Addon_Dependencies[i])
                            {
                                if (Search_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Search_hasDep_Result.Length];
                                    for (int c = 0; c < Search_hasDep_Result.Length; c++)
                                        tmp[c] = Search_hasDep_Result[c];

                                    Search_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Search_hasDep_Result.Length; c++)
                                        Search_hasDep_Result[c] = tmp[c];

                                    Search_hasDep_Result[Search_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_hasDep_Result = new int[1];
                                    Search_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
                else if (mode == 2)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Title[i].ToLower())
                            {
                                if (Search_Title_Result.Length > 0)
                                {
                                    tmp = new int[Search_Title_Result.Length];
                                    for (int c = 0; c < Search_Title_Result.Length; c++)
                                        tmp[c] = Search_Title_Result[c];

                                    Search_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Title_Result[c] = tmp[c];

                                    Search_Title_Result[Search_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Title_Result = new int[1];
                                    Search_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Author[i].ToLower())
                            {
                                if (Search_Author_Result.Length > 0)
                                {
                                    tmp = new int[Search_Author_Result.Length];
                                    for (int c = 0; c < Search_Author_Result.Length; c++)
                                        tmp[c] = Search_Author_Result[c];

                                    Search_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Author_Result[c] = tmp[c];

                                    Search_Author_Result[Search_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Author_Result = new int[1];
                                    Search_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Notes[i].ToLower())
                            {
                                if (Search_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Search_Notes_Result.Length];
                                    for (int c = 0; c < Search_Notes_Result.Length; c++)
                                        tmp[c] = Search_Notes_Result[c];

                                    Search_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Search_Notes_Result.Length; c++)
                                        Search_Notes_Result[c] = tmp[c];

                                    Search_Notes_Result[Search_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Notes_Result = new int[1];
                                    Search_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Search_hasDep_Result.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Dependencies[i].ToLower())
                            {
                                if (Search_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Search_hasDep_Result.Length];
                                    for (int c = 0; c < Search_hasDep_Result.Length; c++)
                                        tmp[c] = Search_hasDep_Result[c];

                                    Search_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Search_hasDep_Result.Length; c++)
                                        Search_hasDep_Result[c] = tmp[c];

                                    Search_hasDep_Result[Search_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_hasDep_Result = new int[1];
                                    Search_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
                else if (mode == 3)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Title[i]) == true)
                            {
                                if (Search_Title_Result.Length > 0)
                                {
                                    tmp = new int[Search_Title_Result.Length];
                                    for (int c = 0; c < Search_Title_Result.Length; c++)
                                        tmp[c] = Search_Title_Result[c];

                                    Search_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Title_Result[c] = tmp[c];

                                    Search_Title_Result[Search_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Title_Result = new int[1];
                                    Search_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Author[i]) == true)
                            {
                                if (Search_Author_Result.Length > 0)
                                {
                                    tmp = new int[Search_Author_Result.Length];
                                    for (int c = 0; c < Search_Author_Result.Length; c++)
                                        tmp[c] = Search_Author_Result[c];

                                    Search_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Author_Result[c] = tmp[c];

                                    Search_Author_Result[Search_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Author_Result = new int[1];
                                    Search_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Notes[i]) == true)
                            {
                                if (Search_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Search_Notes_Result.Length];
                                    for (int c = 0; c < Search_Notes_Result.Length; c++)
                                        tmp[c] = Search_Notes_Result[c];

                                    Search_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_Notes_Result[c] = tmp[c];

                                    Search_Notes_Result[Search_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_Notes_Result = new int[1];
                                    Search_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Search_hasDep_Result.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Dependencies[i]) == true)
                            {
                                if (Search_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Search_hasDep_Result.Length];
                                    for (int c = 0; c < Search_hasDep_Result.Length; c++)
                                        tmp[c] = Search_hasDep_Result[c];

                                    Search_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Search_hasDep_Result[c] = tmp[c];

                                    Search_hasDep_Result[Search_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Search_hasDep_Result = new int[1];
                                    Search_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
            }
            Reconstruct_Search_Results();
        }
        private void Filter_Engine(string parameter, bool title, bool author, bool notes, bool hasDep, int mode)
        {
            Filter_Title_Result = new int[0];
            Filter_Author_Result = new int[0];
            Filter_Notes_Result = new int[0];
            Filter_hasDep_Result = new int[0];

            int[] tmp;
            if (parameter == WildCard)
            {
                if (title == true)
                {
                    Filter_Title_Result = new int[Addon_Title.Length];
                    for (int i = 0; i < Addon_Title.Length; i++)
                        Filter_Title_Result[i] = i;
                }
                if (author == true)
                {
                    Filter_Author_Result = new int[Addon_Author.Length];
                    for (int i = 0; i < Addon_Author.Length; i++)
                        Filter_Author_Result[i] = i;
                }
                if (notes == true)
                {
                    Filter_Notes_Result = new int[Addon_Notes.Length];
                    for (int i = 0; i < Addon_Notes.Length; i++)
                        Filter_Notes_Result[i] = i;
                }
                if (hasDep == true)
                {
                    Filter_hasDep_Result = new int[Addon_Dependencies.Length];
                    for (int i = 0; i < Addon_Dependencies.Length; i++)
                        Filter_hasDep_Result[i] = i;
                }

            }
            else
            {
                if (mode == 1)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (parameter == Addon_Title[i])
                            {
                                if (Filter_Title_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Title_Result.Length];
                                    for (int c = 0; c < Filter_Title_Result.Length; c++)
                                        tmp[c] = Filter_Title_Result[c];

                                    Filter_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Title_Result[c] = tmp[c];

                                    Filter_Title_Result[Filter_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Title_Result = new int[1];
                                    Filter_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (parameter == Addon_Author[i])
                            {
                                if (Filter_Author_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Author_Result.Length];
                                    for (int c = 0; c < Filter_Author_Result.Length; c++)
                                        tmp[c] = Filter_Author_Result[c];

                                    Filter_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Author_Result[c] = tmp[c];

                                    Filter_Author_Result[Filter_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Author_Result = new int[1];
                                    Filter_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (parameter == Addon_Notes[i])
                            {
                                if (Filter_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Notes_Result.Length];
                                    for (int c = 0; c < Filter_Notes_Result.Length; c++)
                                        tmp[c] = Filter_Notes_Result[c];

                                    Filter_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Filter_Notes_Result.Length; c++)
                                        Filter_Notes_Result[c] = tmp[c];

                                    Filter_Notes_Result[Filter_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Notes_Result = new int[1];
                                    Filter_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Filter_hasDep_Result.Length; i++)
                        {
                            if (parameter == Addon_Dependencies[i])
                            {
                                if (Filter_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Filter_hasDep_Result.Length];
                                    for (int c = 0; c < Filter_hasDep_Result.Length; c++)
                                        tmp[c] = Filter_hasDep_Result[c];

                                    Filter_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Filter_hasDep_Result.Length; c++)
                                        Filter_hasDep_Result[c] = tmp[c];

                                    Filter_hasDep_Result[Filter_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_hasDep_Result = new int[1];
                                    Filter_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
                else if (mode == 2)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Title[i].ToLower())
                            {
                                if (Filter_Title_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Title_Result.Length];
                                    for (int c = 0; c < Filter_Title_Result.Length; c++)
                                        tmp[c] = Filter_Title_Result[c];

                                    Filter_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Title_Result[c] = tmp[c];

                                    Filter_Title_Result[Filter_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Title_Result = new int[1];
                                    Filter_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Author[i].ToLower())
                            {
                                if (Filter_Author_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Author_Result.Length];
                                    for (int c = 0; c < Filter_Author_Result.Length; c++)
                                        tmp[c] = Filter_Author_Result[c];

                                    Filter_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Author_Result[c] = tmp[c];

                                    Filter_Author_Result[Filter_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Author_Result = new int[1];
                                    Filter_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Notes[i].ToLower())
                            {
                                if (Filter_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Notes_Result.Length];
                                    for (int c = 0; c < Filter_Notes_Result.Length; c++)
                                        tmp[c] = Filter_Notes_Result[c];

                                    Filter_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Filter_Notes_Result.Length; c++)
                                        Filter_Notes_Result[c] = tmp[c];

                                    Filter_Notes_Result[Filter_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Notes_Result = new int[1];
                                    Filter_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Filter_hasDep_Result.Length; i++)
                        {
                            if (parameter.ToLower() == Addon_Dependencies[i].ToLower())
                            {
                                if (Filter_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Filter_hasDep_Result.Length];
                                    for (int c = 0; c < Filter_hasDep_Result.Length; c++)
                                        tmp[c] = Filter_hasDep_Result[c];

                                    Filter_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < Filter_hasDep_Result.Length; c++)
                                        Filter_hasDep_Result[c] = tmp[c];

                                    Filter_hasDep_Result[Filter_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_hasDep_Result = new int[1];
                                    Filter_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
                else if (mode == 3)
                {
                    if (title == true)
                    {
                        for (int i = 0; i < Addon_Title.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Title[i]) == true)
                            {
                                if (Filter_Title_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Title_Result.Length];
                                    for (int c = 0; c < Filter_Title_Result.Length; c++)
                                        tmp[c] = Filter_Title_Result[c];

                                    Filter_Title_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Title_Result[c] = tmp[c];

                                    Filter_Title_Result[Filter_Title_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Title_Result = new int[1];
                                    Filter_Title_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (author == true)
                    {
                        for (int i = 0; i < Addon_Author.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Author[i]) == true)
                            {
                                if (Filter_Author_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Author_Result.Length];
                                    for (int c = 0; c < Filter_Author_Result.Length; c++)
                                        tmp[c] = Filter_Author_Result[c];

                                    Filter_Author_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Author_Result[c] = tmp[c];

                                    Filter_Author_Result[Filter_Author_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Author_Result = new int[1];
                                    Filter_Author_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (notes == true)
                    {
                        for (int i = 0; i < Addon_Notes.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Notes[i]) == true)
                            {
                                if (Filter_Notes_Result.Length > 0)
                                {
                                    tmp = new int[Filter_Notes_Result.Length];
                                    for (int c = 0; c < Filter_Notes_Result.Length; c++)
                                        tmp[c] = Filter_Notes_Result[c];

                                    Filter_Notes_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_Notes_Result[c] = tmp[c];

                                    Filter_Notes_Result[Filter_Notes_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_Notes_Result = new int[1];
                                    Filter_Notes_Result[0] = i;
                                }
                            }
                        }
                    }
                    if (hasDep == true)
                    {
                        for (int i = 0; i < Filter_hasDep_Result.Length; i++)
                        {
                            if (Engine_Contains(parameter, Addon_Dependencies[i]) == true)
                            {
                                if (Filter_hasDep_Result.Length > 0)
                                {
                                    tmp = new int[Filter_hasDep_Result.Length];
                                    for (int c = 0; c < Filter_hasDep_Result.Length; c++)
                                        tmp[c] = Filter_hasDep_Result[c];

                                    Filter_hasDep_Result = new int[tmp.Length + 1];
                                    for (int c = 0; c < tmp.Length; c++)
                                        Filter_hasDep_Result[c] = tmp[c];

                                    Filter_hasDep_Result[Filter_hasDep_Result.Length - 1] = i;
                                }
                                else
                                {
                                    Filter_hasDep_Result = new int[1];
                                    Filter_hasDep_Result[0] = i;
                                }
                            }
                        }
                    }
                }
            }
            Reconstruct_Filter_Results();
        }
        private void Reconstruct_Search_Results()
        {
            int tmp;
            int tmpID = 0;
            int offset = 0;
            int[] tmplist;
            bool[] used;
            bool usetmp = false;
            int EO = 0;

            Results = new int[Search_Title_Result.Length + Search_Author_Result.Length + Search_Notes_Result.Length + Search_hasDep_Result.Length];

            if (Search_Title_Result.Length > 0)
            {
                for (int i = 0; i < Search_Title_Result.Length; i++)
                    Results[i] = Search_Title_Result[i];
            }
            if (Search_Author_Result.Length > 0)
            {
                for (int i = Search_Title_Result.Length; i < Search_Author_Result.Length + Search_Title_Result.Length; i++)
                    Results[i] = Search_Author_Result[i - Search_Title_Result.Length];
            }
            if (Search_Notes_Result.Length > 0)
            {
                for (int i = Search_Title_Result.Length + Search_Author_Result.Length; i < Search_Notes_Result.Length + Search_Author_Result.Length + Search_Title_Result.Length; i++)
                    Results[i] = Search_Notes_Result[i - Search_Author_Result.Length - Search_Title_Result.Length];
            }
            if (Search_hasDep_Result.Length > 0)
            {
                for (int i = Search_Title_Result.Length + Search_Author_Result.Length + Search_Notes_Result.Length; i < Search_hasDep_Result.Length + Search_Notes_Result.Length + Search_Author_Result.Length + Search_Title_Result.Length; i++)
                    Results[i] = Search_hasDep_Result[i - Search_Notes_Result.Length - Search_Author_Result.Length - Search_Title_Result.Length];
            }

            // Filter Duplicate Entries
            for (int i = 0; i < Results.Length; i++)
            {
                for (int c = i + 1; c < Results.Length; c++)
                {
                    if (Results[i] == Results[c])
                    {
                        tmplist = new int[Results.Length];
                        for (int f = 0; f < Results.Length; f++)
                            tmplist[f] = Results[f];
                        Results = new int[Results.Length - 1];
                        for (int f = 0; f < tmplist.Length; f++)
                        {
                            if (c != f)
                            {
                                Results[f - offset] = tmplist[f];
                            }
                            else
                                offset += 1;
                        }
                        offset = 0;
                    }
                }
            }

            // Double Check (Yes you may think this is redundant, but there
            // are random scenarios where a random double pops up, and this
            // was the easiest way...so no u.
            for (int i = 0; i < Results.Length; i++)
            {
                for (int c = i + 1; c < Results.Length; c++)
                {
                    if (Results[i] == Results[c])
                    {
                        tmplist = new int[Results.Length];
                        for (int f = 0; f < Results.Length; f++)
                            tmplist[f] = Results[f];
                        Results = new int[Results.Length - 1];
                        for (int f = 0; f < tmplist.Length; f++)
                        {
                            if (c != f)
                            {
                                Results[f - offset] = tmplist[f];
                            }
                            else
                                offset += 1;
                        }
                        offset = 0;
                    }
                }
            }

            // Organize
            offset = 0;
            tmplist = new int[Results.Length];
            used = new bool[Results.Length];
            for (int f = 0; f < Results.Length; f++)
                tmplist[f] = Results[f];

            for (int i = 0; i < Results.Length; i++)
            {
                for (int f = 0; f < Results.Length; f++)
                    tmplist[f] = Results[f];

                tmp = Results[i];
                for (int c = i; c < Results.Length; c++)
                {
                    if (Results[c] < tmp)
                    {
                        tmp = Results[c];
                        tmpID = c;
                        usetmp = true;
                    }
                    EO = c;
                }
                Results[i] = tmp;
                if (usetmp == true)
                    Results[tmpID] = tmplist[i];
                else
                    Results[EO] = tmplist[EO];
                usetmp = false;
            }
        }
        private void Reconstruct_Filter_Results()
        {
            int tmp;
            int tmpID = 0;
            int offset = 0;
            int[] tmplist;
            bool[] used;
            bool usetmp = false;
            int EO = 0;

            // Prepare for incoming Excludes
            if (ExcludeList.Length > 0)
            {
                tmplist = new int[ExcludeList.Length];
                for (int i = 0; i < ExcludeList.Length; i++)
                    tmplist[i] = ExcludeList[i];
                ExcludeList = new int[ExcludeList.Length + Filter_Title_Result.Length + Filter_Author_Result.Length + Filter_Notes_Result.Length + Filter_hasDep_Result.Length];
                for (int i = 0; i < tmplist.Length; i++)
                    ExcludeList[i] = tmplist[i];
                offset = tmplist.Length;
            }
            else
                ExcludeList = new int[Filter_Title_Result.Length + Filter_Author_Result.Length + Filter_Notes_Result.Length + Filter_hasDep_Result.Length];

            if (Filter_Title_Result.Length > 0)
            {
                for (int i = 0; i < Filter_Title_Result.Length; i++)
                    ExcludeList[i + offset] = Filter_Title_Result[i];
            }
            if (Filter_Author_Result.Length > 0)
            {
                for (int i = Filter_Title_Result.Length; i < Filter_Author_Result.Length + Filter_Title_Result.Length; i++)
                    ExcludeList[i + offset] = Filter_Author_Result[i - Filter_Title_Result.Length];
            }
            if (Filter_Notes_Result.Length > 0)
            {
                for (int i = Filter_Title_Result.Length + Filter_Author_Result.Length; i < Filter_Notes_Result.Length + Filter_Author_Result.Length + Filter_Title_Result.Length; i++)
                    ExcludeList[i + offset] = Filter_Notes_Result[i - Filter_Author_Result.Length - Filter_Title_Result.Length];
            }
            if (Filter_hasDep_Result.Length > 0)
            {
                for (int i = Filter_Title_Result.Length + Filter_Author_Result.Length + Filter_Notes_Result.Length; i < Filter_hasDep_Result.Length + Filter_Notes_Result.Length + Filter_Author_Result.Length + Filter_Title_Result.Length; i++)
                    ExcludeList[i + offset] = Filter_hasDep_Result[i - Filter_Notes_Result.Length - Filter_Author_Result.Length - Filter_Title_Result.Length];
            }

            // Filter Duplicate Entries
            offset = 0;
            for (int i = 0; i < ExcludeList.Length; i++)
            {
                for (int c = i + 1; c < ExcludeList.Length; c++)
                {
                    if (ExcludeList[i] == ExcludeList[c])
                    {
                        tmplist = new int[ExcludeList.Length];
                        for (int f = 0; f < ExcludeList.Length; f++)
                            tmplist[f] = ExcludeList[f];
                        ExcludeList = new int[ExcludeList.Length - 1];
                        for (int f = 0; f < tmplist.Length; f++)
                        {
                            if (c != f)
                            {
                                ExcludeList[f - offset] = tmplist[f];
                            }
                            else
                                offset += 1;
                        }
                        offset = 0;
                    }
                }
            }

            // Double Check (shh. sometimes it fails the first time)/
            offset = 0;
            for (int i = 0; i < ExcludeList.Length; i++)
            {
                for (int c = i + 1; c < ExcludeList.Length; c++)
                {
                    if (ExcludeList[i] == ExcludeList[c])
                    {
                        tmplist = new int[ExcludeList.Length];
                        for (int f = 0; f < ExcludeList.Length; f++)
                            tmplist[f] = ExcludeList[f];
                        ExcludeList = new int[ExcludeList.Length - 1];
                        for (int f = 0; f < tmplist.Length; f++)
                        {
                            if (c != f)
                            {
                                ExcludeList[f - offset] = tmplist[f];
                            }
                            else
                                offset += 1;
                        }
                        offset = 0;
                    }
                }
            }

            // Organize
            offset = 0;
            tmplist = new int[ExcludeList.Length];
            used = new bool[ExcludeList.Length];
            for (int f = 0; f < ExcludeList.Length; f++)
                tmplist[f] = ExcludeList[f];

            for (int i = 0; i < ExcludeList.Length; i++)
            {
                for (int f = 0; f < ExcludeList.Length; f++)
                    tmplist[f] = ExcludeList[f];

                tmp = ExcludeList[i];
                for (int c = i; c < ExcludeList.Length; c++)
                {
                    if (ExcludeList[c] < tmp)
                    {
                        tmp = ExcludeList[c];
                        tmpID = c;
                        usetmp = true;
                    }
                    EO = c;
                }
                ExcludeList[i] = tmp;
                if (usetmp == true)
                    ExcludeList[tmpID] = tmplist[i];
                else
                    ExcludeList[EO] = tmplist[EO];
                usetmp = false;
            }
        }
    }
}